package com.dkt.wap.configuration;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import com.dkt.base.JsonUtil;
import com.dkt.base.NetConsts;
import com.dkt.base.Resps;
import com.dkt.base.domain.User;
import com.dkt.wap.service.UserSrv;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private UserSrv UserSrv;

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(UserSrv);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.servletApi().disable();
        http.requestCache().disable();
        

        //http.formLogin().loginPage("/login");

//		http.authorizeRequests().mvcMatchers("/login").permitAll();
		http.authorizeRequests().antMatchers("/order/add").hasRole("BIZ");
		http.authorizeRequests().anyRequest().authenticated();

		http.formLogin().successHandler(new AuthenticationSuccessHandler() {
			@Override
			public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
					Authentication authentication) throws IOException, ServletException {
				User user = (User)authentication.getPrincipal();
				response.setContentType("application/json;charset=UTF-8");
				
				request.getSession().setAttribute("member", authentication.getPrincipal());
				
				Resps<User> resps = new Resps<>();
				resps.setRc(NetConsts.RC_SUCCESS);
				resps.setMsg(new String[] {"login success"});
				resps.setData(user);
				response.getWriter().write(JsonUtil.obj2Json(resps));
				response.getWriter().close();
			}
		}).failureHandler(new AuthenticationFailureHandler() {
			@Override
			public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
					AuthenticationException exception) throws IOException, ServletException {
				response.setContentType("application/json;charset=UTF-8");
				response.setStatus(HttpStatus.UNAUTHORIZED.value());
				Resps<Object> resps = new Resps<Object>();
				if (exception instanceof DisabledException) {
					resps.setRc(NetConsts.RC_ACCOUNT_DISABLED);
					resps.setMsg(new String[] { "该账户已被禁用" });
				} else if (exception instanceof AccountExpiredException) {
					resps.setRc(NetConsts.RC_ACCOUNT_EXPIRED);
					resps.setMsg(new String[] { "该帐户已过期" });
				} else if (exception instanceof CredentialsExpiredException) {
					resps.setRc(NetConsts.RC_CREDENTIALS_EXPIRED);
					resps.setMsg(new String[] { "登陆凭证已经过期，请重新登陆" });
				} else if (exception instanceof LockedException) {
					resps.setRc(NetConsts.RC_ACCOUNT_Locked);
					resps.setMsg(new String[] { "该账户被锁定" });
				} else if (exception instanceof AuthenticationCredentialsNotFoundException) {
					resps.setRc(NetConsts.RC_CREDENTIALS_NOT_FOUND);
					resps.setMsg(new String[] { "身份验证凭证未找到" });
				} else if (exception instanceof BadCredentialsException) {
					resps.setRc(NetConsts.RC_BAD_CREDENTIALS);
					resps.setMsg(new String[] { "密码错误" });
				} else if (exception instanceof UsernameNotFoundException) {
					resps.setRc(NetConsts.RC_USERNAME_NOT_FOUNDD);
					resps.setMsg(new String[] { "该账户名不存在" });
				} else {
					resps.setRc("E08");
					resps.setMsg(new String[] { "登录时发生错误，请联系系统管理员" });
				}
				response.getWriter().write(JsonUtil.obj2Json(resps));
				response.getWriter().close();
			}
		});

		// 登出处理。
		http.logout().logoutSuccessHandler((request, response, authentication) -> {
			response.setContentType("application/json;charset=UTF-8");
			Resps<Object> resps = new Resps<Object>();
			resps.setRc(NetConsts.RC_SUCCESS);
			response.getWriter().write(JsonUtil.obj2Json(resps));
			response.getWriter().close();
		});

		// 未登录，却访问需要登录的接口时的处理
		http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
			response.sendRedirect("doLogin");
		});
		// 已登录，但当前用户没有访问的某个接口的权限时的处理
		http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) -> {
			response.setContentType("application/json;charset=UTF-8");
			response.setStatus(401);
			Resps<Object> resps = new Resps<Object>();
			resps.setRc("E09");
			resps.setMsg(new String[] { "您无权访问该资源!" });
			response.getWriter().write(JsonUtil.obj2Json(resps));
			response.getWriter().close();
		});
	}
	
	@Override
	public void configure(WebSecurity web) throws Exception {
		// 不需要经过SpringSecurity的过滤器的URLs
		web.ignoring()
			.mvcMatchers("/global.css","/js/*","/svg/*","/img/*")
			// 商品
			.mvcMatchers("/doSearch","/search","/goods","/goods_details")
			// 首页
			.mvcMatchers("/index")
			// 订单
			.mvcMatchers("/order","/doAddOrder")
			// 登录
			.mvcMatchers("/doLogin")
			.mvcMatchers("/item/list");
	}

}
